#include <sxQOpenGL_Viewport.h>
#include <sxQGL_Viewport.h>
#include <sxViewportController.h>

const Sx::Graphics::Color4f DEFAULT_CLEAR_COLOR = Sx::Graphics::Color4f();

Sx::QtInterface::QOpenGL_Viewport::QOpenGL_Viewport(QWidget* parent, const std::shared_ptr<OpenGL_Context>& context, unsigned int fps, Qt::WFlags flags) : QViewport(parent, context, fps, flags) {
	this->viewport = new QGL_Viewport(this);
	this->viewport->addViewportListener(this);
	this->context = context;
}

Sx::QtInterface::QOpenGL_Viewport::QOpenGL_Viewport(QWidget* parent, QOpenGL_Viewport* share, unsigned int fps, Qt::WFlags flags) : 
	QViewport(parent, (share == nullptr) ? nullptr : share->context, fps, flags) {

	this->viewport = new QGL_Viewport(this, share->viewport);
	this->viewport->addViewportListener(this);
	this->context = share->context;
}

Sx::QtInterface::QOpenGL_Viewport::~QOpenGL_Viewport() {
	delete this->viewport;
}

/* 
 * The following set of functions simply pass the update, render, and resize
 * messages from Qt to the QViewport architecture/interface.
 */
inline void Sx::QtInterface::QOpenGL_Viewport::initializeGL() { this->initialize(); }
inline void Sx::QtInterface::QOpenGL_Viewport::paintGL() { this->render(); }
inline void Sx::QtInterface::QOpenGL_Viewport::resizeGL(int width, int height) { this->resize(width, height); }

bool Sx::QtInterface::QOpenGL_Viewport::initialize() {
	if ( this->context == nullptr ) {
		std::cerr << "[QOpenGL_Viewport:initialize] Error: Provided context is a nullptr." << std::endl;
		std::cerr << "  OpenGL Viewport has not been initialized." << std::endl;
		return false;
	}

	//--------------------------------------------------------------------------
	// Initialize the context if it hasn't been already.
	//--------------------------------------------------------------------------
	if ( this->context->isInitialized() == false ) this->context->initialize();

	if ( this->controller == nullptr ) {
		std::cerr << "[QOpenGL_Viewport:initialize] Warning: OpenGL Viewport has no controller." << std::endl;
		std::cerr << "  If the OpenGL context is valid then the viewport will be black." << std::endl;
		glClearColor(DEFAULT_CLEAR_COLOR.getR(), DEFAULT_CLEAR_COLOR.getG(), DEFAULT_CLEAR_COLOR.getB(), DEFAULT_CLEAR_COLOR.getA());
	}
	else {
		if ( this->controller->isInitialized() == false ) this->controller->initialize();
		glClearColor(this->controller->getClearColor().getR(), this->controller->getClearColor().getG(), this->controller->getClearColor().getB(), this->controller->getClearColor().getA());
	}

	return true;
}

void Sx::QtInterface::QOpenGL_Viewport::render() const {
	if ( this->context == nullptr ) return;
	if ( this->controller == nullptr ) return;
	
	this->context->preRender();
		this->controller->render();
	this->context->postRender();
}

void Sx::QtInterface::QOpenGL_Viewport::reRender() const {
	if ( this->viewport == nullptr ) return;
	this->render();
	this->viewport->updateGL();
}

void Sx::QtInterface::QOpenGL_Viewport::resize(int width, int height) {
	this->view.setSize(this->width(), this->height());

	if ( this->viewport == nullptr ) return;
	this->viewport->resize(this->width(), this->height());
	
	if ( this->controller == nullptr ) return;
	this->controller->resize(this->width(), this->height());
}

void Sx::QtInterface::QOpenGL_Viewport::resizeEvent(QResizeEvent* e) {
	this->resize(this->width(), this->height());
}
